* <para>focus: the widget has focus</para>
* </listitem>
* <listitem>
- * <para>indeterminate: the widget is showing the hint text</para>
+ * <para>indeterminate: the widget is showing the hint text or actor</para>
* </listitem>
* </itemizedlist>
*/
#include "st-im-text.h"
#include "st-icon.h"
+#include "st-label.h"
#include "st-widget.h"
#include "st-texture-cache.h"
#include "st-clipboard.h"
PROP_PRIMARY_ICON,
PROP_SECONDARY_ICON,
PROP_HINT_TEXT,
+ PROP_HINT_ACTOR,
PROP_TEXT,
PROP_INPUT_PURPOSE,
PROP_INPUT_HINTS,
struct _StEntryPrivate
{
ClutterActor *entry;
- gchar *hint;
ClutterActor *primary_icon;
ClutterActor *secondary_icon;
+ ClutterActor *hint_actor;
+
gfloat spacing;
- gboolean hint_visible;
gboolean capslock_warning_shown;
gboolean has_ibeam;
st_entry_set_hint_text (entry, g_value_get_string (value));
break;
+ case PROP_HINT_ACTOR:
+ st_entry_set_hint_actor (entry, g_value_get_object (value));
+ break;
+
case PROP_TEXT:
st_entry_set_text (entry, g_value_get_string (value));
break;
break;
case PROP_HINT_TEXT:
- g_value_set_string (value, priv->hint);
+ g_value_set_string (value, st_entry_get_hint_text (ST_ENTRY (gobject)));
+ break;
+
+ case PROP_HINT_ACTOR:
+ g_value_set_object (value, priv->hint_actor);
break;
case PROP_TEXT:
}
static void
-st_entry_finalize (GObject *object)
+st_entry_update_hint_visibility (StEntry *self)
{
- StEntryPrivate *priv = ST_ENTRY_PRIV (object);
+ StEntryPrivate *priv = ST_ENTRY_PRIV (self);
+ gboolean hint_visible =
+ priv->hint_actor != NULL &&
+ strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "") == 0 &&
+ !HAS_FOCUS (priv->entry);
- g_free (priv->hint);
- priv->hint = NULL;
+ if (priv->hint_actor)
+ g_object_set (priv->hint_actor, "visible", hint_visible, NULL);
- G_OBJECT_CLASS (st_entry_parent_class)->finalize (object);
+ if (hint_visible)
+ st_widget_add_style_pseudo_class (ST_WIDGET (self), "indeterminate");
+ else
+ st_widget_remove_style_pseudo_class (ST_WIDGET (self), "indeterminate");
}
static void
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- gfloat icon_w;
+ gfloat hint_w, icon_w;
st_theme_node_adjust_for_height (theme_node, &for_height);
min_width_p,
natural_width_p);
+ if (priv->hint_actor)
+ {
+ clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
+
+ if (min_width_p && hint_w > *min_width_p)
+ *min_width_p = hint_w;
+
+ if (natural_width_p && hint_w > *natural_width_p)
+ *natural_width_p = hint_w;
+ }
+
if (priv->primary_icon)
{
clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- gfloat icon_h;
+ gfloat hint_h, icon_h;
st_theme_node_adjust_for_width (theme_node, &for_width);
min_height_p,
natural_height_p);
+ if (priv->hint_actor)
+ {
+ clutter_actor_get_preferred_height (priv->hint_actor, -1, NULL, &hint_h);
+
+ if (min_height_p && hint_h > *min_height_p)
+ *min_height_p = hint_h;
+
+ if (natural_height_p && hint_h > *natural_height_p)
+ *natural_height_p = hint_h;
+ }
+
if (priv->primary_icon)
{
clutter_actor_get_preferred_height (priv->primary_icon,
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- ClutterActorBox content_box, child_box, icon_box;
+ ClutterActorBox content_box, child_box, icon_box, hint_box;
gfloat icon_w, icon_h;
+ gfloat hint_w, hint_h;
gfloat entry_h, min_h, pref_h, avail_h;
ClutterActor *left_icon, *right_icon;
+ gboolean is_rtl;
+
+ is_rtl = clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL;
- if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL)
+ if (is_rtl)
{
right_icon = priv->primary_icon;
left_icon = priv->secondary_icon;
child_box.x2 = MAX (child_box.x1, child_box.x2 - icon_w - priv->spacing);
}
+ if (priv->hint_actor)
+ {
+ /* now allocate the hint actor */
+ hint_box = child_box;
+
+ clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
+ clutter_actor_get_preferred_height (priv->hint_actor, -1, NULL, &hint_h);
+
+ if (is_rtl)
+ hint_box.x1 = hint_box.x2 - hint_w;
+ else
+ hint_box.x2 = hint_box.x1 + hint_w;
+
+ hint_box.y1 = ceil (content_box.y1 + avail_h / 2 - hint_h / 2);
+ hint_box.y2 = hint_box.y1 + hint_h;
+
+ clutter_actor_allocate (priv->hint_actor, &hint_box, flags);
+ }
+
clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
&min_h, &pref_h);
ClutterActor *actor)
{
StEntry *entry = ST_ENTRY (actor);
- StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
GdkKeymap *keymap;
- /* remove the hint if visible */
- if (priv->hint && priv->hint_visible)
- {
- priv->hint_visible = FALSE;
-
- clutter_text_set_text (text, "");
- }
+ st_entry_update_hint_visibility (entry);
keymap = gdk_keymap_get_for_display (gdk_display_get_default ());
keymap_state_changed (keymap, entry);
g_signal_connect (keymap, "state-changed",
G_CALLBACK (keymap_state_changed), entry);
- st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
st_widget_add_style_pseudo_class (ST_WIDGET (actor), "focus");
clutter_text_set_cursor_visible (text, TRUE);
}
ClutterActor *actor)
{
StEntry *entry = ST_ENTRY (actor);
- StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
GdkKeymap *keymap;
st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "focus");
- /* add a hint if the entry is empty */
- if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
- {
- priv->hint_visible = TRUE;
+ st_entry_update_hint_visibility (entry);
- clutter_text_set_text (text, priv->hint);
- st_widget_add_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
- }
clutter_text_set_cursor_visible (text, FALSE);
remove_capslock_feedback (entry);
gobject_class->set_property = st_entry_set_property;
gobject_class->get_property = st_entry_get_property;
- gobject_class->finalize = st_entry_finalize;
gobject_class->dispose = st_entry_dispose;
actor_class->get_preferred_width = st_entry_get_preferred_width;
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec);
+ pspec = g_param_spec_object ("hint-actor",
+ "Hint Actor",
+ "An actor to display when the entry is not focused "
+ "and the text property is empty",
+ CLUTTER_TYPE_ACTOR,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_HINT_ACTOR, pspec);
+
pspec = g_param_spec_string ("text",
"Text",
"Text of the entry",
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
priv = st_entry_get_instance_private (entry);
- if (priv->hint_visible)
+ if (clutter_actor_is_visible (priv->hint_actor))
return "";
else
return clutter_text_get_text (CLUTTER_TEXT (priv->entry));
priv = st_entry_get_instance_private (entry);
- /* set a hint if we are blanking the entry */
- if (priv->hint
- && text && !strcmp ("", text)
- && !HAS_FOCUS (priv->entry))
- {
- text = priv->hint;
- priv->hint_visible = TRUE;
- st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
- }
- else
- {
- st_widget_remove_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
-
- priv->hint_visible = FALSE;
- }
-
clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
+ st_entry_update_hint_visibility (entry);
+
g_object_notify (G_OBJECT (entry), "text");
}
st_entry_set_hint_text (StEntry *entry,
const gchar *text)
{
- StEntryPrivate *priv;
+ StWidget *label;
g_return_if_fail (ST_IS_ENTRY (entry));
- priv = st_entry_get_instance_private (entry);
-
- g_free (priv->hint);
-
- priv->hint = g_strdup (text);
-
- if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "")
- && !HAS_FOCUS (priv->entry))
- {
- priv->hint_visible = TRUE;
-
- clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
- st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
- }
+ label = st_label_new (text);
+ st_entry_set_hint_actor (ST_ENTRY (entry), CLUTTER_ACTOR (label));
}
/**
const gchar *
st_entry_get_hint_text (StEntry *entry)
{
+ StEntryPrivate *priv;
+
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
- return ((StEntryPrivate *)ST_ENTRY_PRIV (entry))->hint;
+ priv = ST_ENTRY_PRIV (entry);
+
+ if (priv->hint_actor != NULL && ST_IS_LABEL (priv->hint_actor))
+ return st_label_get_text (ST_LABEL (priv->hint_actor));
+
+ return NULL;
}
/**
return priv->secondary_icon;
}
+/**
+ * st_entry_set_hint_actor:
+ * @entry: a #StEntry
+ * @hint_actor: (allow-none): a #ClutterActor
+ *
+ * Set the hint actor of the entry to @hint_actor
+ */
+void
+st_entry_set_hint_actor (StEntry *entry,
+ ClutterActor *hint_actor)
+{
+ StEntryPrivate *priv;
+
+ g_return_if_fail (ST_IS_ENTRY (entry));
+
+ priv = ST_ENTRY_PRIV (entry);
+
+ if (priv->hint_actor != NULL)
+ {
+ clutter_actor_remove_child (CLUTTER_ACTOR (entry), priv->hint_actor);
+ priv->hint_actor = NULL;
+ }
+
+ if (hint_actor != NULL)
+ {
+ priv->hint_actor = hint_actor;
+ clutter_actor_add_child (CLUTTER_ACTOR (entry), priv->hint_actor);
+ }
+
+ st_entry_update_hint_visibility (entry);
+
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
+}
+
+/**
+ * st_entry_get_hint_actor:
+ * @entry: a #StEntry
+ *
+ * Returns: (transfer none): a #ClutterActor
+ */
+ClutterActor *
+st_entry_get_hint_actor (StEntry *entry)
+{
+ StEntryPrivate *priv;
+
+ g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
+
+ priv = ST_ENTRY_PRIV (entry);
+ return priv->hint_actor;
+}
+
/******************************************************************************/
/*************************** ACCESSIBILITY SUPPORT ****************************/
/******************************************************************************/